﻿using System;
using System.Threading;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// EventWaitHandle扩展类,通知正在等待的线程已发生事件
    /// </summary>
    [System.Runtime.InteropServices.ComVisible(true)]
    public class EventWaitHandleEx : IDisposable
    {
        /// <summary>
        /// 通知正在等待的线程已发生事件对象
        /// </summary>
        private readonly EventWaitHandle _eventWaitHandle;

        /// <summary>
        /// 对象是否已释放[true:已释放;false:未释放]
        /// </summary>
        private bool _isDisposed = false;



        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="eventWaitHandle">EventWaitHandle</param>
        public EventWaitHandleEx(EventWaitHandle eventWaitHandle)
        {
            this._eventWaitHandle = eventWaitHandle;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="initialState"></param>
        /// <param name="mode"></param>
        public EventWaitHandleEx(bool initialState, EventResetMode mode)
        {
            if (mode == EventResetMode.AutoReset)
            {
                this._eventWaitHandle = new AutoResetEvent(initialState);
            }
            else if (mode == EventResetMode.ManualReset)
            {
                this._eventWaitHandle = new ManualResetEvent(initialState);
            }
            else
            {
                throw new NotImplementedException(mode.ToString());
            }
        }





        /// <summary>
        /// 将事件状态设置为非终止，从而导致线程受阻[如果该操作成功，则为 true；否则为 false]
        /// </summary>
        /// <returns>如果该操作成功，则为 true；否则为 false</returns>
        public bool Reset()
        {
            if (this._isDisposed)
            {
                return false;
            }

            try
            {
                return this._eventWaitHandle.Reset();
            }
            catch (ObjectDisposedException)
            {
                return false;
            }
        }


        /// <summary>
        /// 将事件状态设置为有信号，从而允许一个或多个等待线程继续执行[如果该操作成功，则为 true；否则为 false]
        /// </summary>
        /// <returns>如果该操作成功，则为 true；否则为 false</returns>
        public bool Set()
        {
            if (this._isDisposed)
            {
                return false;
            }

            try
            {
                return this._eventWaitHandle.Set();
            }
            catch (ObjectDisposedException)
            {
                return false;
            }
        }






        /// <summary>
        /// 对Token,WaitHandle方法的包装,Blocks the current thread until the current System.Threading.WaitHandle receives a signal. 
        /// </summary>
        /// <returns>true if the current instance receives a signal. 
        /// If the current instance is never signaled, 
        /// System.Threading.WaitHandle.WaitOne(System.Int32,System.Boolean) never returns.</returns>
        public bool WaitOne()
        {
            if (this._isDisposed)
            {
                return false;
            }

            return WaitHandleEx.WaitOne(this._eventWaitHandle);
        }

        /// <summary>
        /// 阻止当前线程，直到当前 System.Threading.WaitHandle 收到信号，同时使用 32 位带符号整数指定时间间隔（以毫秒为单位）
        /// </summary>
        /// <param name="millisecondsTimeout">等待的毫秒数，或为 System.Threading.Timeout.Infinite (-1)，表示无限期等待</param>
        /// <returns></returns>
        public bool WaitOne(int millisecondsTimeout)
        {
            if (this._isDisposed)
            {
                return false;
            }

            return WaitHandleEx.WaitOne(this._eventWaitHandle, millisecondsTimeout);
        }

        /// <summary>
        /// 对Token,WaitHandle方法的包装,Blocks the current thread until the current System.Threading.WaitHandle receives a signal, using a 32-bit signed integer to specify the time interval in milliseconds.
        /// </summary>
        /// <param name="timeout">A System.TimeSpan that represents the number of milliseconds to wait, or a System.TimeSpan that represents -1 milliseconds to wait indefinitely</param>
        /// <returns>true if the current instance receives a signal; otherwise, false</returns>
        public bool WaitOne(TimeSpan timeout)
        {
            if (this._isDisposed)
            {
                return false;
            }

            return WaitHandleEx.WaitOne(this._eventWaitHandle, timeout);
        }




        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
        }

        /// <summary>
        /// 释放资源方法
        /// </summary>
        /// <param name="isDispose">是否释放标识</param>
        protected virtual void Dispose(bool isDispose)
        {
            if (this._isDisposed)
            {
                return;
            }

            this._eventWaitHandle.Dispose();
            this._isDisposed = true;
        }
    }
}
